
package com.scalar.chiptrack.alarms;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Date;

import com.scalar.ScalarException;
import com.scalar.chiptrack.utils.Mailer;
import com.scalar.chiptrack.utils.StringUtils;
import com.scalar.chiptrack.utils.ConfigManager;
import com.scalar.chiptrack.db.DBTransaction;
import com.scalar.chiptrack.alarms.dao.AlarmDAO;
import com.scalar.chiptrack.commons.Constants;


public class Alarm {

    // PRIORITY LEVELS
    public static final String ALARM_PRIORITY_EXTREME = "EXTREME";
    public static final String ALARM_PRIORITY_SEVERE = "SEVERE";
    public static final String ALARM_PRIORITY_HIGH = "HIGH";
    public static final String ALARM_PRIORITY_NORMAL = "NORMAL";
    public static final String ALARM_PRIORITY_LOW = "LOW";

    // ALARM STATES 
    public static final String ALARM_STATUS_NEW = "NEW";
    public static final String ALARM_STATUS_ACTIVATED = "ACTIVATED";
    public static final String ALARM_STATUS_UPDATED = "UPDATED";
    public static final String ALARM_STATUS_CLOSED = "CLOSED";

    // ALARM RESPONSES
    public static final String ALARM_RESPONSE_ACCEPT = "ACCEPT";
    public static final String ALARM_RESPONSE_REJECT = "REJECT";
    public static final String ALARM_RESPONSE_NOT_RESPONDED_YET = "NOT RESPONDED YET";
    
    public static final String ALARM_DEFUALT_TYPE = "UNDEFINED";
    public static final long DEFAULT_TIME_LIMIT_TO_RESPOND =  17280000;  // 48 X 60 X 60 X 1000 -> 2 days (in milli sec)
    
    // Alarm State
    private String m_name = null;
    private int m_id = -1;   //Unique ID generated internally (by database)
    private String m_type = null;
    
    private AlarmUser m_from = null;
    private Map m_recipients = null;
    private String m_lastUpdatedBy = null;
    
    private String m_currentState = ALARM_STATUS_NEW;
    private String m_message = "";
    private String m_subject = "";
    private String m_priority = ALARM_PRIORITY_NORMAL;
    
    private long m_createdOn = System.currentTimeMillis();
    private long m_expiresOn = -1;  // never expires
    private long m_respondBefore = -1;
    
    private List m_comments = null;
    
    
    public Alarm() {
        m_type = ALARM_DEFUALT_TYPE;
    }
    
    public Alarm (String name, String type, AlarmUser from) throws Exception {

        if (name == null) {
            throw new ScalarException ("Alarm name cannot be null");
        }

        if (from == null) {
            throw new ScalarException ("Alarm originator cannot be null");
        }

        m_name = name;
        
        if (type != null) {
            m_type = type;
        }
        else {
            m_type = ALARM_DEFUALT_TYPE;
        }
        
        m_from = from;
        
        m_recipients = new HashMap();
        m_comments = new ArrayList();
        
        m_currentState = ALARM_STATUS_NEW;
        m_lastUpdatedBy = from.getName();
    }

    public Alarm (String name, String type, AlarmUser from, String priority, long createdOn, long expiresOn) throws Exception {
        
        this (name, type, from);
        m_priority = priority;
        m_createdOn = createdOn;
        m_expiresOn = expiresOn;
    }
    
    
    public String getName() {
        return m_name;
    }
    public void setName (String name) {
        m_name = name;
    }

    public String getType() {
        return m_type;
    }
    public void setType (String type) {
        if (type != null) {
            m_type = type;
        }
    }
    
    public void setId (int id) {
        m_id = id;
    }  
    public int getId() {
	return m_id;
    }

    public String getPriority() {
	return m_priority;
    }
    public void setPriority (String priority) {
        m_priority = priority;
    }

    public String getCurrentState() {
    	return m_currentState;
    }
    public void setCurrentState (String state) {
        m_currentState = state;
    }

    public AlarmUser getOriginator() {
	return m_from;
    }
    public void setOriginator (AlarmUser from) {
        if (from != null) {
            m_from = from;
        }
    }

    public void addRecipient (AlarmUser user) {
        if (user != null) {
            m_recipients.put(user.getName(), user);
        }
    }

    public void setRecipients (List users) {
        if (users == null) {
            return;
        }
        // Added by Prabhanjan on 13 November 2003 to clear the list before setting new user list.
        m_recipients.clear();
        AlarmUser user = null;
        for (int i=0; i<users.size(); i++) {
            user = (AlarmUser) users.get(i);
            m_recipients.put (user.getName(), user);
        }
    }

    public Iterator getRecipients() {
    	return m_recipients.values().iterator();
    }

    public long getCreatedOn() {
	return m_createdOn;
    }
    public void setCreatedOn (long createdOn) {
        m_createdOn = createdOn;
    }
    
    public long getExpiresOn() {
        return m_expiresOn;
    }
    public void setExpiresOn (long expiresOn) {
        m_expiresOn = expiresOn;
    }
    
    public long getRespondBefore() {
        return m_respondBefore;
    }
    public void setRespondBefore (long respondBefore) {
        m_respondBefore = respondBefore;
    }
    

    public void addComment( DBTransaction dbTransaction, Comment comment ) throws ScalarException
    {
        addComment( dbTransaction, comment, true );
    }  

    public void addComment (DBTransaction dbTransaction, Comment comment, boolean saveIt) throws ScalarException
    {
        
        if ( m_currentState == ALARM_STATUS_NEW )
        {
            throw new ScalarException ("Alarm is not activated");
        }
        
        if ( comment != null ) 
        {
            m_comments.add (comment);
           
            m_currentState = ALARM_STATUS_UPDATED;
            m_lastUpdatedBy = comment.getCreatedBy();
            
            if( saveIt == false )
            {
                return;     // Dont save it... return
            }
            
            AlarmDAO.insertComment( dbTransaction, m_id, comment, m_currentState, m_lastUpdatedBy );
        }
    }

    public List getComments() {
	return m_comments;
    }

    public List getCommentsByUser (String userName) {
        if (userName == null) {
            return null;
        }

        ArrayList commentList = new ArrayList();
        int size = m_comments.size();
        Comment comment = null;

        for (int i=0; i<size; i++) {
            comment = (Comment) m_comments.get(i);
            if (comment.getCreatedBy().equals(userName) == true) {
                commentList.add (comment);
            }
        }

    	return commentList;
    }

    public String getUserResponse (String userName) {
        if (userName == null) {
            return null;
        }

	return ((AlarmUser)m_recipients.get(userName)).getResponse();
    }

    public void setUserResponse (String userName, String response, String comment) throws ScalarException {
        
        if (m_currentState == ALARM_STATUS_NEW) {
            throw new ScalarException ("Alarm is not activated");
        }
        
        if ((response != null) && (userName != null))
        {
            AlarmUser user = (AlarmUser) m_recipients.get (userName);
            if (user != null) {
                user.setResponse (response);
            }
        }

        if (comment != null) {
            m_comments.add (new Comment (userName, comment));
        }

        m_currentState = ALARM_STATUS_UPDATED;
        m_lastUpdatedBy = userName;
        
        AlarmDAO.insertUserResponse (userName, m_id, response, comment, m_currentState, m_lastUpdatedBy);
    }

    public void setMessage (String message) {
        if (message != null) {
            m_message = message;
        }
    }
    public String getMessage() {
        return m_message;
    }


    public String getSubject() {
        return m_subject;
    }

    public void setSubject(String subject) {
        this.m_subject = subject;
    }

    public String getLastUpdatedBy() {
        return m_lastUpdatedBy;
    }
    
    public void setLastUpdatedBy (String lastUpdatedBy) {
        m_lastUpdatedBy = lastUpdatedBy;
    }
    
    public void activate (DBTransaction dbTransaction) throws ScalarException {
        
        if (m_from == null) {
            throw new ScalarException ("Alarm Originator is not set, Alarm cannot be activated.");
        }
        
        if (m_recipients.size() == 0) {
            throw new ScalarException ("At least one recipient should be added to activate this Alarm");
        }

        m_currentState = ALARM_STATUS_ACTIVATED;
        AlarmDAO.insertAlarm (dbTransaction, this);
    }

    public void close() throws Exception {
        if (m_currentState == ALARM_STATUS_NEW) {
            throw new ScalarException ("Alarm is not activated");
        }
        
        m_currentState = ALARM_STATUS_CLOSED;
        m_lastUpdatedBy = m_from.getName();
        
        AlarmDAO.updateAlarmState (m_id, m_currentState, m_lastUpdatedBy);
    }

    public void notifyRecipient (AlarmUser user, boolean showAlarmDetails) throws Exception {
        notifyRecipient (user.getEmail(), showAlarmDetails, null);
    }
    
    public void notifyRecipient (AlarmUser user) throws Exception {
        notifyRecipient (user.getEmail(), true, null); // by default show Alarm Details
    }
    
    public void notifyRecipient (String email) throws Exception {
        notifyRecipient (email, true, null);  // by default show Alarm Details
    }
    
    public void notifyRecipient (String email, boolean showAlarmDetails) throws Exception {
        notifyRecipient (email, showAlarmDetails, null);  
    }
    
    public void notifyRecipient (String email, boolean showAlarmDetails, String messageBody) throws Exception {
        
        if (email == null) throw new ScalarException ("Email ID is null");

        if (m_currentState == ALARM_STATUS_NEW) {
            throw new ScalarException ("Alarm is not activated");
        }
        
        String from = m_from.getEmail();
        StringBuffer to = new StringBuffer();
        String subject = "Alarm [" + m_name + "] -- " + m_currentState;
        
        String message = "";
        if ((messageBody == null) || (messageBody.trim().length() == 0)) {
            if (showAlarmDetails) {
                message += this + "\n";
            }
            message += "Message from Originator: \n" + m_message;
        }
        else {
            message = messageBody;
        }

        Mailer.send (from, email, subject, message, Mailer.CONTENT_TYPE_HTML);
    }
    
    public void notifyAllRecipients () throws Exception {
        notifyAllRecipients (true, null);     // by default show Alarm Details
    }
    
    public void notifyAllRecipients (String messageBody) throws Exception {
        notifyAllRecipients (true, messageBody);     // by default show Alarm Details
    }
    
    public void notifyAllRecipients (boolean showAlarmDetails)  throws Exception {
        notifyAllRecipients (showAlarmDetails, null);
    }
    
    public void notifyAllRecipients( boolean showAlarmDetails, String messageBody ) throws Exception
    {
        String subject = null;

        if ( messageBody == null )
        {
            messageBody = "";
        }
        //String from = m_from.getEmail();
        String from = ConfigManager.getFromEmailId( Constants.FROM_EMAIL_SALES_GROUP_NAME );
        StringBuffer to = new StringBuffer();
        String toMails = null;
        
        Iterator users = m_recipients.values().iterator();

        while( users.hasNext() )
        {
            to = to.append ( ( ( AlarmUser) users.next() ).getEmail() ).append( "," );
        }

        if( m_subject == null || m_subject.trim().length() == 0 )
        {
            subject = "Notification [" + m_name + "] -- " + m_currentState;
        }
        else
        {
            subject = m_subject;
        }

        if ( showAlarmDetails )
        {
            m_message += messageBody;
        }
        
        String message = this.toHTML();
        if( to != null && to.toString().trim().length() > 0 )
        {
            toMails = StringUtils.removeDuplicateEmailIds( to.toString() );
            //Mailer.send ( from, to.toString(), subject, message, Mailer.CONTENT_TYPE_HTML );
            Mailer.send (from, toMails, null, null, subject, message, null, Mailer.CONTENT_TYPE_HTML, false); //need to remove qualify emails, as we are sending mails to sales persons
        }
        else
        {
            System.out.println ( "WARNING!! At least one recipient email should be present to Send Notification" );
        }
    }

    
    public void notifyAllRecipients (String subject, String message) throws Exception {
        
        String from = m_from.getEmail();

        StringBuffer to = new StringBuffer();
        
        Iterator users = m_recipients.values().iterator();
        while (users.hasNext()) {
            to = to.append (((AlarmUser)users.next()).getEmail()).append (",");
        }
                
        Mailer.send (from, to.toString(), subject, message, Mailer.CONTENT_TYPE_HTML);
    }
    
    
    /**
     * Returns the string representation of this Alarm Object 
     */
    public String toHTML() {

        StringBuffer buf = new StringBuffer();

        buf.append ("<table border='0' width='80%' align='center' style='FONT-SIZE: 8pt;  FONT-FAMILY: Verdana' cellpadding='3' cellspacing='0'>");
        
        buf.append ("<tr><td colspan='2' bgcolor='#ccccff' align='center'><SPAN style='FONT-WEIGHT: bold; FONT-SIZE: 8pt;  FONT-FAMILY: Verdana'><strong>Notification Details</strong></span></td></tr>");
        buf.append ("<tr bgcolor='#e6e6e6'><td>Notification Name:</td><td>").append (m_name).append ("</td></tr>");
        /*buf.append ("<tr bgcolor='#e6e6e6'><td>Notification Type:</td><td>").append (m_type).append ("</td></tr>");
        buf.append ("<tr bgcolor='#e6e6e6'><td>Created By:</td><td>").append (m_from.getName()).append ("</td></tr>");
        buf.append ("<tr bgcolor='#e6e6e6'><td>Created On:</td><td>").append (StringUtils.formatDateToString(new Date (m_createdOn))).append ("</td></tr>");

        buf.append ("<tr bgcolor='#e6e6e6'><td>Expires On:</td>");
        if (m_expiresOn == -1) {
            buf.append ("<td>Never Expires</td></tr>");
        }
        else {
            buf.append ("<td>").append (StringUtils.formatDateToString(new Date (m_expiresOn))).append ("</td></tr>");
        }

        buf.append ("<tr bgcolor='#e6e6e6'><td>Priority:</td><td>").append (m_priority).append ("</td></tr>");
        buf.append ("<tr bgcolor='#e6e6e6'><td>Alarm Current State:</td><td>").append (m_currentState).append ("</td></tr>");*/
        buf.append ("<tr bgcolor='#e6e6e6'><td>Last Updated By:</td><td>").append (m_lastUpdatedBy).append ("</td></tr>");


        String bgColor[] = {"#e6e6e6", "#e6e6e6"};

        /*Object[] recipients = m_recipients.values().toArray();

        buf.append ("<tr><td colspan='2'><br></td></tr>");
        buf.append ("<tr><td colspan='2' bgcolor='#ccccff' align='left'>Responses:</td></tr>");

        for (int i=0; i<recipients.length; i++)
        {
            buf.append ("<tr bgcolor='#e6e6e6'><td>").append (((AlarmUser)recipients[i]).getName()).append (":</td><td>").append (((AlarmUser)recipients[i]).getResponse()).append ("</td></tr>\n");
        }*/

        String commentString = null;

        if ((m_comments != null) && (m_comments.size() > 0)) {
            buf.append ("<tr><td colspan='2'><br></td></tr>");

            Comment comment = null;
            int size = m_comments.size();

            buf.append ("<tr><td colspan='2'><table border='0' width='100%' align='center' style=' FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Verdana'>");
            buf.append ("<tr bgcolor='#ccccff'><td colspan='3' align='left'>Comments:</td></tr>");

            for (int i=0; i<size; i++) {
                comment = (Comment) m_comments.get (i);
                commentString = comment.getComment();

                if ((commentString != null) && (commentString.trim().length() != 0))
                {
                    buf.append ("<tr bgcolor='#e6e6e6'><td width='15%'>").append (comment.getCreatedBy());
                    buf.append ("</td><td width='25%'>").append (StringUtils.formatDateToString(new Date (comment.getCreatedOn()))).append ("</td><td width='60%'>").append (comment.getComment());
                    buf.append ("</td></tr>");
                }
            }
            
            buf.append ("</table></td></tr>");
        }

        buf.append ("<tr><td colspan='2'><br></td></tr>");
        buf.append ("<tr><td colspan='2'>Message from Originator: <br>" + m_message + "</td></tr>");
        buf.append ("</table>");
        
        return buf.toString();
    }
    public void notifyAllRecipientsForInternalComments( String messageBody ) throws Exception
    {
        String subject = null;
        if ( messageBody == null )
        {
            messageBody = "";
        }
        //String from = m_from.getEmail();
        String from = ConfigManager.getFromEmailId( Constants.FROM_EMAIL_SALES_GROUP_NAME );
        StringBuffer to = new StringBuffer();

        Iterator users = m_recipients.values().iterator();
        while( users.hasNext() )
        {
            to = to.append ( ( ( AlarmUser) users.next() ).getEmail() ).append( "," );
        }

        if( m_subject == null || m_subject.trim().length() == 0 )
        {
            subject = "Notification [" + m_name + "] -- " + m_currentState;
        }
        else
        {
            subject = m_subject;
        }

        try
        {
            if( to != null && to.toString().trim().length() > 0 )
            {
                Mailer.send (from, to.toString(), null, null, subject, messageBody, null, Mailer.CONTENT_TYPE_HTML, false); //need to remove qualify emails, as we are sending mails to sales persons
            }
            else
            {
                System.out.println ( "WARNING!! At least one recipient email should be present to Send Notification" );
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    
}